#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include<cstdarg>
#include<ctime>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<pthread.h>
enum
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
enum
{
    Screen = 10,
    OneFile,
    ClassFile
};

std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "debuf";
    case INFO:
        return "info";
    case WARNING:
        return "warning";
    case ERROR:
        return "error";
    case FATAL:
        return "fatal";
    default:
        return "Unknown";
    }
}
const int defaultstyle = Screen;//默认10
const std::string default_filename = "log.";//默认文件名前缀；
const std::string logdir = "log";
class Log
{
    public:
    Log()
    :style(defaultstyle)
    ,filename(default_filename)
    {
        mkdir(logdir.c_str(),0775);//创建日志目录
    }
    void Enable(int sty)
    {
        style = sty;
    }
    std::string TimeStampExLocalTime()//当前时间；
    {
        time_t currtime = time(nullptr);
        struct tm *format_time = localtime(&currtime);
        char time_buffer[128];
        snprintf(time_buffer,sizeof(time_buffer),"%d-%d-%d %d:%d:%d",
                                format_time->tm_year+1900,
                                format_time->tm_mon+1,
                                format_time->tm_mday,
                                format_time->tm_hour,
                                format_time->tm_min,
                                format_time->tm_sec
                            );
                            return time_buffer;
      }
      void WriteLogToonefile(const std::string &logname,const std::string &message)//将日志消息写入文件
      {
        umask(0);
        int fd = open(logname.c_str(),O_CREAT|O_WRONLY|O_APPEND,0666);//此文件不存在就创建，只写，如果文件已经有内容
        //这次打开文件所写的数据附加到文件末尾，不覆盖原来的内容
        if(fd<0)
        {
            return ;
        }
        write(fd,message.c_str(),message.size());//打开xxx文件，并获取文件描述符，把消息写入文件中，写入成功，返回写入的字节数，失败返回-1
        close(fd);
    }
    void WriteLogToClassFile(const std::string &levelstr,const std::string &message)//
    {
        std::string logname = logdir;
        logname +="/";
        logname +=filename;
        logname+=levelstr;
        WriteLogToonefile(logname,message);
    }
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    void WriteLog(const std::string &levelstr,const std::string message)//写日志
    {
        pthread_mutex_lock(&lock);
        switch (style)
        {
        case Screen://打印到屏幕上
            std::cout<<message;
            break;
        case OneFile: //一个文件写入到日志类里面
            WriteLogToClassFile("all",message);
            break;
        case ClassFile:
            WriteLogToClassFile(levelstr,message);
            break;
        default:
            break;
        }
        pthread_mutex_unlock(&lock);
    }
    void logMessage(int level,const char *format,...)//日志消息
    {
        char leftbuffer[1024];//左缓冲区
        std::string levelstr = LevelToString(level);
        std::string timestr = TimeStampExLocalTime();
        std::string idstr = std::to_string(getpid());
        
        char rightbuffer[1024];//右缓冲区
        va_list args;
        va_start(args,format);
        vsnprintf(rightbuffer,sizeof(rightbuffer),format,args);
        va_end(args);
        snprintf(leftbuffer,sizeof(leftbuffer),"[%s][%s][%s]",levelstr.c_str(),timestr.c_str(),idstr.c_str());
        std::string loginfo = leftbuffer;
        loginfo+=rightbuffer;
        WriteLog(levelstr,loginfo);

    }
    ~Log()
    {}
    private:
    int style;
    std::string filename;//文件名
};
Log lg;
class Conf
{
public:
Conf()
{
  lg.Enable(Screen);
}
~Conf()
{}
};
Conf conf;